using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.ApplicationBlocks.Data;
using System.Data.SqlClient;
using Microsoft.SharedSource.SqlServer.MDDE.Middleware;
using System.Xml;
using System.IO;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;

namespace Microsoft.SharedSource.SqlServer.MDDE.ManagementStudio
{
    public partial class ExportPackage : Form
    {
        string repositoryConnectionString;
        string templateName;
        string packageName;

        enum TargetLocation
        {
            MetadataTable,
            FileSystem,
            SqlServer
        }

        enum ServerAuthentication
        {
            WindowsAuthentication,
            SQLServerAuthentication
        }

        public ExportPackage(string repositoryConnectionString,
            string templateName, string packageName)
        {
            InitializeComponent();
            this.repositoryConnectionString = repositoryConnectionString;
            this.packageName = packageName;
            this.templateName = templateName;

            // Populate the location combobox.
            DataTable dt = new DataTable();
            dt.Columns.Add("Name", typeof(string));
            dt.Columns.Add("Value", typeof(TargetLocation));
            dt.Rows.Add("SQL Server", TargetLocation.SqlServer);
            dt.Rows.Add("File System", TargetLocation.FileSystem);
            dt.Rows.Add("Metadata Table", TargetLocation.MetadataTable);
            cmbInstanceLocation.DataSource = dt;
            cmbInstanceLocation.ValueMember = "Value";
            cmbInstanceLocation.DisplayMember = "Name";

            // Populate the authentication combobox.
            DataTable dtAuth = new DataTable();
            dtAuth.Columns.Add("Name", typeof(string));
            dtAuth.Columns.Add("Value", typeof(ServerAuthentication));
            dtAuth.Rows.Add("SQL Server Authentication",
                ServerAuthentication.SQLServerAuthentication);
            dtAuth.Rows.Add("Windows Authentication",
                ServerAuthentication.WindowsAuthentication);
            cmbAuthentication.DataSource = dtAuth;
            cmbAuthentication.ValueMember = "Value";
            cmbAuthentication.DisplayMember = "Name";
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void cmbInstanceLocation_SelectedIndexChanged(
            object sender, EventArgs e)
        {
            ApplyEnablingLogic();
        }

        private void ExportInstance_Load(object sender, EventArgs e)
        {
            cmbInstanceLocation.SelectedIndex = 0;
            ApplyEnablingLogic();
        }

        private void ApplyEnablingLogic()
        {
            // Enable the appropriate location.
            if (cmbInstanceLocation.SelectedValue is int &&
                (TargetLocation)cmbInstanceLocation.SelectedValue
                == TargetLocation.MetadataTable)
            {
                grpAuthentication.Enabled = true;
                grpMetadataTable.Enabled = true;
                grpFile.Enabled = false;
            }

            if (cmbInstanceLocation.SelectedValue is int &&
                (TargetLocation)cmbInstanceLocation.SelectedValue
                == TargetLocation.FileSystem)
            {
                grpAuthentication.Enabled = false;
                grpMetadataTable.Enabled = false;
                grpFile.Enabled = true;
            }

            if (cmbInstanceLocation.SelectedValue is int &&
                (TargetLocation)cmbInstanceLocation.SelectedValue
                == TargetLocation.SqlServer)
            {
                grpAuthentication.Enabled = true;
                grpMetadataTable.Enabled = false;
                grpFile.Enabled = false;
            }

            // Enable/Disable Username, Password.
            if (cmbAuthentication.SelectedValue is int
                && (ServerAuthentication)cmbAuthentication.SelectedValue ==
                ServerAuthentication.SQLServerAuthentication)
            {
                txtUserName.Enabled = true;
                txtPassword.Enabled = true;
            }

            if (cmbAuthentication.SelectedValue is int
                && (ServerAuthentication)cmbAuthentication.SelectedValue ==
                ServerAuthentication.WindowsAuthentication)
            {
                txtUserName.Enabled = false;
                txtPassword.Enabled = false;
            }
        }

        private void cmbAuthentication_SelectedIndexChanged(
            object sender, EventArgs e)
        {
            ApplyEnablingLogic();
        }

        private void cmbServer_TextChanged(object sender, EventArgs e)
        {
            // Clear up the databases.
            cmbDatabase.DataSource = null;
        }

        private void cmbDatabase_DropDown(object sender, EventArgs e)
        {
            // Populate the database list if empty.
            if (cmbDatabase.DataSource == null)
            {
                try
                {
                    // Get the database list.
                    DataSet dtDatabases = SqlHelper.ExecuteDataset(
                        PrepareConnectionString(),
                        CommandType.Text,
                        "SELECT name FROM sys.databases");

                    if (dtDatabases.Tables[0].Rows.Count > 0)
                    {
                        cmbDatabase.DataSource = dtDatabases.Tables[0];
                        cmbDatabase.DisplayMember = "name";
                        cmbDatabase.ValueMember = "name";
                    }
                }
                catch
                {
                    // Gobble up all exceptions
                }
            }
        }

        private string PrepareConnectionString()
        {
            // Prepare a connection string.
            SqlConnectionStringBuilder sb =
                new SqlConnectionStringBuilder();
            sb.DataSource = cmbServer.Text;
            if (cmbAuthentication.SelectedValue is int
                && (ServerAuthentication)cmbAuthentication.SelectedValue ==
                ServerAuthentication.WindowsAuthentication)
                sb.IntegratedSecurity = true;
            else
            {
                sb.IntegratedSecurity = false;
                sb.UserID = txtUserName.Text;
                sb.Password = txtPassword.Text;
            }

            sb.InitialCatalog = cmbDatabase.Text;

            return sb.ConnectionString;
        }

        private void cmbDatabase_TextChanged(object sender, EventArgs e)
        {
            // Clear up the tables.
            cmbTable.DataSource = null;
        }

        private void cmbTable_DropDown(object sender, EventArgs e)
        {
            // Populate the tables list if empty.
            if (cmbTable.DataSource == null)
            {
                PopulateTables();
            }
        }

        private void PopulateTables()
        {
            try
            {
                // Get the database list.
                DataSet dsTables = SqlHelper.ExecuteDataset(
                    PrepareConnectionString(),
                    CommandType.Text,
                    "SELECT name FROM sys.tables");

                if (dsTables.Tables[0].Rows.Count > 0)
                {
                    cmbTable.DataSource = dsTables.Tables[0];
                    cmbTable.DisplayMember = "name";
                    cmbTable.ValueMember = "name";
                }
            }
            catch
            {
                // Gobble up all exceptions
            }
        }

        private void btnNew_Click(object sender, EventArgs e)
        {
            CreateInstanceInformationTable frmCreateTable =
                new CreateInstanceInformationTable(PrepareConnectionString());
            frmCreateTable.ShowDialog();

            // Refresh the tables list.
            PopulateTables();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            // Perform validations.
            if (cmbInstanceLocation.SelectedValue is int
                && (TargetLocation)cmbInstanceLocation.SelectedValue ==
                TargetLocation.SqlServer)
            {
                MessageBox.Show(
                    "Export to sql server not implemented.",
                    "Not implemented",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);

                return;
            }


            if (!(cmbInstanceLocation.SelectedValue is int) ||
                cmbInstanceLocation.SelectedValue is int
                && (TargetLocation)cmbInstanceLocation.SelectedValue ==
                TargetLocation.MetadataTable && ValidateTable() == false ||
                cmbInstanceLocation.SelectedValue is int
                && (TargetLocation)cmbInstanceLocation.SelectedValue ==
                TargetLocation.FileSystem && ValidatePath() == false)
                return;

            // Disable all controls.
            foreach (Control ctrl in this.Controls)
                ctrl.Enabled = false;
            this.Cursor = Cursors.WaitCursor;


            switch ((TargetLocation)cmbInstanceLocation.SelectedValue)
            {
                case TargetLocation.FileSystem:
                    try
                    {
                        XmlDocument package = MDDEManager.GetPackage(repositoryConnectionString,
                            packageName, templateName, null);

                        package.Save(txtInstancePath.Text);

                        this.Close();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(
                            "Could not export package to file system.\n" +
                            ex.Message,
                            "Error",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error);
                    }
                    break;

                case TargetLocation.MetadataTable:

                    try
                    {
                        // Get package details.
                        XmlDocument xPackageDetails = MDDEManager.GetPackageDetails(
                            repositoryConnectionString, templateName, packageName);

                        //// Get template name.
                        //string templateName =
                        //    xPackageDetails.SelectSingleNode(
                        //    "//MDDEPackage").Attributes["TemplateName"].Value;

                        // Get the changes xml.
                        XmlNode xChanges =
                            xPackageDetails.SelectSingleNode(
                            "//ChangesFromTemplate");

                        // Begin a transaction.
                        SqlConnection conn = null;
                        SqlTransaction txn = null;

                        // Populate table.
                        try
                        {
                            conn = new SqlConnection(PrepareConnectionString());
                            conn.Open();

                            // Check for the existence of previous information.
                            int cntMetadataRows =
                               Convert.ToInt32(SqlHelper.ExecuteScalar(conn,
                                CommandType.Text,
                                "SELECT COUNT(1) FROM [" + cmbTable.Text +
                                "] WHERE TemplateName = '" + templateName +
                                "' AND InstanceName = '" + packageName + "'"));

                            DialogResult choice = DialogResult.Yes;

                            if (cntMetadataRows > 0)
                            {
                                choice =
                                    MessageBox.Show(
                                    "The metadata information for " +
                                    packageName +
                                    " is already present in the metadata table. Do you want to overwrite the earlier information?", "Overwrite Information", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                            }

                            if (choice == DialogResult.Yes)
                            {
                                txn = conn.BeginTransaction();

                                #region Delete earlier information

                                SqlHelper.ExecuteNonQuery(txn,
                                    CommandType.Text,
                                    "DELETE FROM [" + cmbTable.Text +
                                    "] WHERE TemplateName = '" + templateName +
                                    "' AND InstanceName = '" + packageName + "'");

                                #endregion

                                foreach (XmlNode xComp in
                                    xChanges.SelectNodes("PackageChanges/Component"))
                                {
                                    #region Insert Instance Scalar Properties

                                    foreach (XmlNode xScalarProp in
                                        xComp.SelectNodes("./Properties/Property"))
                                    {
                                        SqlParameter[] scalarPropParams =
                                            new SqlParameter[7];
                                        scalarPropParams[0] =
                                            new SqlParameter("@templateName",
                                            templateName);
                                        scalarPropParams[1] =
                                            new SqlParameter("@instanceName",
                                            packageName);
                                        scalarPropParams[2] =
                                            new SqlParameter("@componentName",
                                            xComp.Attributes["Name"].Value);
                                        scalarPropParams[3] =
                                            new SqlParameter("@componentType",
                                            "Component");
                                        scalarPropParams[4] =
                                            new SqlParameter("@componentUri",
                                            xComp.Attributes["URL"].Value);
                                        scalarPropParams[5] =
                                            new SqlParameter("@scalarPropertyName",
                                            xScalarProp.Attributes["Name"].Value);
                                        scalarPropParams[6] =
                                            new SqlParameter("@scalarPropertyValue",
                                            xScalarProp.Attributes["Value"].Value);

                                        SqlHelper.ExecuteNonQuery(
                                            txn,
                                            CommandType.Text,
                                            "INSERT INTO [" + cmbTable.Text + "](" +
                                            "TemplateName, InstanceName, ComponentName, " +
                                            "ComponentType, ComponentUri, " +
                                            "ScalarPropertyName, ScalarPropertyValue) " +
                                            "VALUES (@templateName, @instanceName, " +
                                            "@componentName, @componentType, @componentUri, " +
                                            "@scalarPropertyName, @scalarPropertyValue)",
                                            scalarPropParams);
                                    }

                                    #endregion

                                    #region Insert Column Collections

                                    foreach (XmlNode xCollection in
                                        xComp.SelectNodes("./CollectionInformation/Collection"))
                                    {

                                        #region Insert Collection Properties

                                        foreach (XmlNode xCollProp in
                                            xCollection.SelectNodes("./Properties/Property"))
                                        {

                                            SqlParameter[] collPropParams =
                                                new SqlParameter[9];
                                            collPropParams[0] =
                                                new SqlParameter("@templateName",
                                                templateName);
                                            collPropParams[1] =
                                                new SqlParameter("@instanceName",
                                                packageName);
                                            collPropParams[2] =
                                                new SqlParameter("@componentName",
                                                xComp.Attributes["Name"].Value);
                                            collPropParams[3] =
                                                new SqlParameter("@componentType",
                                                "Component");
                                            collPropParams[4] =
                                                new SqlParameter("@componentUri",
                                                xComp.Attributes["URL"].Value);
                                            collPropParams[5] =
                                                new SqlParameter("@columnCollectionType",
                                                xCollection.Attributes["Type"].Value);
                                            collPropParams[6] =
                                                new SqlParameter("@columnCollectionName",
                                                xCollection.Attributes["Name"].Value);
                                            collPropParams[7] =
                                                new SqlParameter("@scalarPropertyName",
                                                xCollProp.Attributes["Name"].Value);
                                            collPropParams[8] =
                                                new SqlParameter("@scalarPropertyValue",
                                                xCollProp.Attributes["Value"].Value);

                                            SqlHelper.ExecuteNonQuery(
                                                txn,
                                                CommandType.Text,
                                                "INSERT INTO [" + cmbTable.Text + "](" +
                                                "TemplateName, InstanceName, ComponentName, " +
                                                "ComponentType, ComponentUri, ColumnCollectionType, " +
                                                "ColumnCollectionName, ScalarPropertyName, " +
                                                "ScalarPropertyValue) " +
                                                "VALUES (@templateName, @instanceName, " +
                                                "@componentName, @componentType, @componentUri, " +
                                                "@columnCollectionType, @columnCollectionName," +
                                                "@scalarPropertyName, @scalarPropertyValue)",
                                                collPropParams);
                                        }

                                        #endregion

                                        #region Insert Collection Columns

                                        foreach (XmlNode xColumn in
                                            xCollection.SelectNodes("./Columns/Column"))
                                        {
                                            foreach (XmlNode xColProp in
                                                xColumn.SelectNodes("./Properties/Property"))
                                            {
                                                SqlParameter[] collPropParams =
                                                    new SqlParameter[10];
                                                collPropParams[0] =
                                                    new SqlParameter("@templateName",
                                                    templateName);
                                                collPropParams[1] =
                                                    new SqlParameter("@instanceName",
                                                    packageName);
                                                collPropParams[2] =
                                                    new SqlParameter("@componentName",
                                                    xComp.Attributes["Name"].Value);
                                                collPropParams[3] =
                                                    new SqlParameter("@componentType",
                                                    "Component");
                                                collPropParams[4] =
                                                    new SqlParameter("@componentUri",
                                                    xComp.Attributes["URL"].Value);
                                                collPropParams[5] =
                                                    new SqlParameter("@columnCollectionType",
                                                    xCollection.Attributes["Type"].Value);
                                                collPropParams[6] =
                                                    new SqlParameter("@columnCollectionName",
                                                    xCollection.Attributes["Name"].Value);
                                                collPropParams[7] =
                                                    new SqlParameter("@columnName",
                                                    xColumn.Attributes["Name"].Value);
                                                collPropParams[8] =
                                                    new SqlParameter("@scalarPropertyName",
                                                    xColProp.Attributes["Name"].Value);
                                                collPropParams[9] =
                                                    new SqlParameter("@scalarPropertyValue",
                                                    xColProp.Attributes["Value"].Value);

                                                SqlHelper.ExecuteNonQuery(
                                                    txn,
                                                    CommandType.Text,
                                                    "INSERT INTO [" + cmbTable.Text + "](" +
                                                    "TemplateName, InstanceName, ComponentName, " +
                                                    "ComponentType, ComponentUri, ColumnCollectionType, " +
                                                    "ColumnCollectionName, ColumnName, " +
                                                    "ScalarPropertyName, " +
                                                    "ScalarPropertyValue) " +
                                                    "VALUES (@templateName, @instanceName, " +
                                                    "@componentName, @componentType, @componentUri, " +
                                                    "@columnCollectionType, @columnCollectionName, " +
                                                    "@columnName, @scalarPropertyName, @scalarPropertyValue)",
                                                    collPropParams);
                                            }
                                        }

                                        #endregion
                                    }

                                    #endregion

                                    #region Insert Component Mappings

                                    foreach (XmlNode xMapping in
                                        xComp.SelectNodes("./Mappings/Mapping"))
                                    {
                                        SqlParameter[] mappingParams =
                                            new SqlParameter[8];
                                        mappingParams[0] =
                                            new SqlParameter("@templateName",
                                            templateName);
                                        mappingParams[1] =
                                            new SqlParameter("@instanceName",
                                            packageName);
                                        mappingParams[2] =
                                            new SqlParameter("@componentName",
                                            xComp.Attributes["Name"].Value);
                                        mappingParams[3] =
                                            new SqlParameter("@componentType",
                                            "Component");
                                        mappingParams[4] =
                                            new SqlParameter("@componentUri",
                                            xComp.Attributes["URL"].Value);
                                        mappingParams[5] =
                                            new SqlParameter("@sourceColumnName",
                                            xMapping.Attributes["SourceColumn"].Value);
                                        mappingParams[6] =
                                            new SqlParameter("@sourceColumnUsage",
                                            xMapping.Attributes["Usage"].Value);
                                        mappingParams[7] =
                                            new SqlParameter("@destinationColumnName",
                                            xMapping.Attributes["DestinationColumn"].Value);

                                        SqlHelper.ExecuteNonQuery(
                                            txn,
                                            CommandType.Text,
                                            "INSERT INTO [" + cmbTable.Text + "](" +
                                            "TemplateName, InstanceName, ComponentName, " +
                                            "ComponentType, ComponentUri, SourceColumnName, " +
                                            "SourceColumnUsage, DestinationColumnName) " +
                                            "VALUES (@templateName, @instanceName, " +
                                            "@componentName, @componentType, @componentUri, " +
                                            "@sourceColumnName, @sourceColumnUsage, " +
                                            "@destinationColumnName)",
                                            mappingParams);
                                    }

                                    #endregion
                                }

                                #region Insert Variables

                                foreach (XmlNode xComp in
                                    xChanges.SelectNodes("PackageChanges/Variable"))
                                {
                                    #region Insert Properties

                                    foreach (XmlNode xScalarProp in
                                        xComp.SelectNodes("./Properties/Property"))
                                    {
                                        SqlParameter[] scalarPropParams =
                                            new SqlParameter[7];
                                        scalarPropParams[0] =
                                            new SqlParameter("@templateName",
                                            templateName);
                                        scalarPropParams[1] =
                                            new SqlParameter("@instanceName",
                                            packageName);
                                        scalarPropParams[2] =
                                            new SqlParameter("@componentName",
                                            xComp.Attributes["Name"].Value);
                                        scalarPropParams[3] =
                                            new SqlParameter("@componentType",
                                            "Variable");
                                        scalarPropParams[4] =
                                            new SqlParameter("@componentUri",
                                            xComp.Attributes["URL"].Value);
                                        scalarPropParams[5] =
                                            new SqlParameter("@scalarPropertyName",
                                            xScalarProp.Attributes["Name"].Value);
                                        scalarPropParams[6] =
                                            new SqlParameter("@scalarPropertyValue",
                                            xScalarProp.Attributes["Value"].Value);

                                        SqlHelper.ExecuteNonQuery(
                                            txn,
                                            CommandType.Text,
                                            "INSERT INTO [" + cmbTable.Text + "](" +
                                            "TemplateName, InstanceName, ComponentName, " +
                                            "ComponentType, ComponentUri, ScalarPropertyName, " +
                                            "ScalarPropertyValue) " +
                                            "VALUES (@templateName, @instanceName, " +
                                            "@componentName, @componentType, @componentUri, " +
                                            "@scalarPropertyName, @scalarPropertyValue)",
                                            scalarPropParams);
                                    }

                                    #endregion
                                }

                                #endregion

                                #region Insert ConnectionManagers

                                foreach (XmlNode xComp in
                                    xChanges.SelectNodes("PackageChanges/ConnectionManager"))
                                {
                                    #region Insert Properties

                                    foreach (XmlNode xScalarProp in
                                        xComp.SelectNodes("./Properties/Property"))
                                    {
                                        SqlParameter[] scalarPropParams =
                                            new SqlParameter[7];
                                        scalarPropParams[0] =
                                            new SqlParameter("@templateName",
                                            templateName);
                                        scalarPropParams[1] =
                                            new SqlParameter("@instanceName",
                                            packageName);
                                        scalarPropParams[2] =
                                            new SqlParameter("@componentName",
                                            xComp.Attributes["Name"].Value);
                                        scalarPropParams[3] =
                                            new SqlParameter("@componentType",
                                            "ConnectionManager");
                                        if (((XmlElement)xComp).HasAttribute("URL"))
                                        {
                                            scalarPropParams[4] =
                                                new SqlParameter("@componentUri",
                                                xComp.Attributes["URL"].Value);
                                        }
                                        else
                                        {
                                            scalarPropParams[4] =
                                                new SqlParameter("@componentUri",
                                                string.Empty);
                                        }

                                        scalarPropParams[5] =
                                            new SqlParameter("@scalarPropertyName",
                                            xScalarProp.Attributes["Name"].Value);
                                        scalarPropParams[6] =
                                            new SqlParameter("@scalarPropertyValue",
                                            xScalarProp.Attributes["Value"].Value);

                                        SqlHelper.ExecuteNonQuery(
                                            txn,
                                            CommandType.Text,
                                            "INSERT INTO [" + cmbTable.Text + "](" +
                                            "TemplateName, InstanceName, ComponentName, " +
                                            "ComponentType, ComponentUri, ScalarPropertyName, " +
                                            "ScalarPropertyValue) " +
                                            "VALUES (@templateName, @instanceName, " +
                                            "@componentName, @componentType, @componentUri, " +
                                            "@scalarPropertyName, @scalarPropertyValue)",
                                            scalarPropParams);
                                    }

                                    #endregion
                                }

                                #endregion

                                // Commit the transaction.
                                txn.Commit();

                                // Close the form.
                                this.Close();
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(
                                "Could not populate metadata table.\n" +
                                ex.Message,
                                "Error",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);

                            if (txn != null)
                                txn.Rollback();
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(
                            "Could not fetch package metadata.\n" +
                            ex.Message,
                            "Error",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error);
                    }

                    break;
            }

            // Enable all controls.
            foreach (Control ctrl in this.Controls)
                ctrl.Enabled = true;
            this.Cursor = Cursors.Default;

            ApplyEnablingLogic();
        }

        private bool ValidatePath()
        {
            // Check if the path is empty.
            if (txtInstancePath.Text == string.Empty)
            {
                MessageBox.Show(
                    "Please select the destination path for instance information file.",
                    "Insufficient information",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation);
                return false;
            }

            // Validate the path.
            try
            {
                if (!Directory.Exists(
                    Path.GetDirectoryName(txtInstancePath.Text)))
                {
                    MessageBox.Show(
                        "Target directory does not exist.",
                        "Invalid path",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Exclamation);
                    return false;
                }
            }
            catch (System.ArgumentException ex)
            {
                MessageBox.Show(
                    ex.Message,
                    "Invalid arguement",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation);
                return false;
            }
            catch (System.IO.PathTooLongException ex)
            {
                MessageBox.Show(
                    ex.Message,
                    "Path Too LongException",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation);
                return false;
            }

            return true;
        }

        private bool ValidateTable()
        {
            if (cmbTable.Text == string.Empty)
            {
                MessageBox.Show(
                    "Please select an instance information table.",
                    "Insufficient information",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation);
                return false;
            }

            // Validate the schema of selected table.
            try
            {
                // BUG: Creation of table allows empty values for 
                // database name but that is not true for OK button click.
                // Use the PrepareConnectionString method here and explicitly
                // fire sql query to fetch schema information rather than
                // relying on SMO.
                Server server =
                    new Server(
                    new ServerConnection(
                    new SqlConnection(PrepareConnectionString())));
                Database database = server.Databases[cmbDatabase.Text];
                Table table = database.Tables[cmbTable.Text];

                if (
                    table.Columns.Contains("TemplateName") &&
                    table.Columns["TemplateName"].
                    DataType.SqlDataType == SqlDataType.NVarChar &&
                    table.Columns.Contains("InstanceName") &&
                    table.Columns["InstanceName"].
                    DataType.SqlDataType == SqlDataType.NVarChar &&
                    table.Columns.Contains("ComponentName") &&
                    table.Columns["ComponentName"].
                    DataType.SqlDataType == SqlDataType.NVarChar &&
                    table.Columns.Contains("ComponentUri") &&
                    table.Columns["ComponentUri"].
                    DataType.SqlDataType == SqlDataType.NVarChar &&
                    table.Columns.Contains("ColumnCollectionType") &&
                    table.Columns["ColumnCollectionType"].
                    DataType.SqlDataType == SqlDataType.NVarChar &&
                    table.Columns.Contains("ColumnCollectionName") &&
                    table.Columns["ColumnCollectionName"].
                    DataType.SqlDataType == SqlDataType.NVarChar &&
                    table.Columns.Contains("ColumnName") &&
                    table.Columns["ColumnName"].
                    DataType.SqlDataType == SqlDataType.NVarChar &&
                    table.Columns.Contains("ScalarPropertyName") &&
                    table.Columns["ScalarPropertyName"].
                    DataType.SqlDataType == SqlDataType.NVarChar &&
                    table.Columns.Contains("ScalarPropertyValue") &&
                    table.Columns["ScalarPropertyValue"].
                    DataType.SqlDataType == SqlDataType.NVarChar &&
                    table.Columns.Contains("SourceColumnName") &&
                    table.Columns["SourceColumnName"].
                    DataType.SqlDataType == SqlDataType.NVarChar &&
                    table.Columns.Contains("SourceColumnUsage") &&
                    table.Columns["SourceColumnUsage"].
                    DataType.SqlDataType == SqlDataType.Bit &&
                    table.Columns.Contains("DestinationColumnName") &&
                    table.Columns["DestinationColumnName"].
                    DataType.SqlDataType == SqlDataType.NVarChar
                    )
                {
                    return true;
                }
                else
                {
                    MessageBox.Show(
                        "Selected table does not conform to the required schema.",
                        "Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                    return false;
                }
            }
            catch
            {
                MessageBox.Show(
                    "Error fetching the table information.",
                    "Error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                return false;
            }
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            SaveFileDialog fd = new SaveFileDialog();
            fd.Title = "Export Package";
            fd.Filter = "DTSX files|*.dtsx";
            fd.ShowDialog();
            txtInstancePath.Text = fd.FileName;
        }
    }
}